/**
 * @describe 二进制文件转换
 * @author 游金宇(KM)
 * @date 2023-01-30 11:38:43
 */

import { Camera, find, log, Node, RenderTexture, UITransform, view, Canvas, Sprite, SpriteFrame, gfx, IRect, math, Rect } from 'cc';

interface capture {
    canvas: HTMLCanvasElement;
    spriteFrame: SpriteFrame;
}
/**
 * 根据节点截图
 * @param {Node} nodeCapture
 * @returns {HTMLCanvasElement} canvas节点
 */
export async function captureNode(nodeCapture: Node): Promise<capture> {
    const size = nodeCapture.getComponent(UITransform)!;
    var worldPos = nodeCapture.getWorldPosition();
    const rect: math.Rect = math.rect(worldPos.x, worldPos.y, size.width, size.height);

    const width = rect.width;
    const height = rect.height;

    let camera = nodeCapture.addComponent(Camera);

    camera.orthoHeight = rect.height / 2;
    camera.projection = Camera.ProjectionType.ORTHO;
    camera.near = 0; /* 默认1，必须改为0否则黑屏 */
    camera.far = 1000;
    camera.visibility = 33554432;
    let texture = new RenderTexture();
    texture.reset({
        width: rect.width,
        height: rect.height,
    });

    camera.targetTexture = texture;
    let canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;

    let ctx = canvas.getContext('2d')!;

    return new Promise(resolve => {
        const timer = setTimeout(() => {
            clearTimeout(timer);
            let data = texture.readPixels();
            if (!data) return
            let rowBytes = width * 4;
            for (let row = 0; row < height; row++) {
                let srow = height - 1 - row;
                let imageData = ctx.createImageData(width, 1);
                let start = srow * width * 4;
                for (let i = 0; i < rowBytes; i++) {
                    imageData.data[i] = data[start + i];
                }
                ctx.putImageData(imageData, 0, row);
            }
            camera.destroy();
            const spriteFrame = new SpriteFrame();
            spriteFrame.texture = texture;
            spriteFrame.flipUVY = true;
            resolve({ canvas, spriteFrame });
        }, 16);
    });
}
/**
 * 将canvas转换为图片URL
 * @param canvas canvas节点
 * @returns {string} 图片URL
 */
export function canvasToDataURL(canvas: HTMLCanvasElement): string {
    let dataURL = canvas.toDataURL('image/jpg', 10);
    return dataURL;
}
/**
 * 将canvas转换为BLOB
 * @param canvas canvas节点
 * @param name 图片名称
 */
function canvasToBlob(canvas: HTMLCanvasElement): Promise<Blob | null> {
    return new Promise((resolve, reject) => {
        canvas.toBlob(
            (blob: Blob | null) => {
                resolve(blob);
            },
            'image/png',
            1.0
        );
    });
}

/**
 * 将节点截图转化为BLOB 并下载到本地
 * @param nodeCapture 节点
 * @param name 图片名称
 */
export async function captureNodeToLocation(nodeCapture: Node, name: string = ''): Promise<SpriteFrame> {
    const { canvas, spriteFrame } = await captureNode(nodeCapture);
    const blob = await canvasToBlob(canvas);
    blob && blobSaveLocation(blob, name);
    return Promise.resolve(spriteFrame);
}

/**
 * 将BLOB转换为图片 下载到本地
 * @param blob
 * @param name
 */
export function blobSaveLocation(blob: Blob, name: string) {
    // 下载完成，创建一个a标签用于下载

    let a = document.createElement('a');

    a.download = name; //保存提示中用作预先填写的文件名

    a.href = URL.createObjectURL(blob);

    document.body.appendChild(a);

    a.click();

    // 在资源下载完成后 清除占用的缓存资源

    const timer = setTimeout(() => {
        URL.revokeObjectURL(a.href);
        document.body.removeChild(a);
        clearTimeout(timer);
    }, 200);
}

/**
 * BLOB二进制转图片url
 * @param blob 二进制文件
 * @param callback 回调函数
 */
export function blobtoDataURL(blob: Blob, callback: Function) {
    var fr = new FileReader();
    fr.onload = (e: ProgressEvent<FileReader>) => {
        log(e);
        callback && callback(e.target!.result);
    };
    fr.readAsDataURL(blob);
}

/**
 * 将图片url转为blob二进制
 * @param {string} url 图片rul
 * @returns {Promise<Blob>} blob文件
 */
export function downloadIamge(url: string): Promise<Blob> {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();

        xhr.open('get', url, true);

        xhr.responseType = 'blob'; //arraybuffer也可以

        xhr.onreadystatechange = () => {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                // 4 DONE 下载操作已完成
                if (xhr.status == 200) {
                    let blob = xhr.response; // response 属性返回响应的正文，取决于 responseType 属性。
                    resolve(blob);
                } else {
                    reject();
                }
            }
        };
        xhr.send(null);
    });
}
